/**
* 
* ====================================================================
*
* @author apov <apov@ymail.com>
*/ 

#pragma once

#include <BaseDefine.h>
#include "Network_IOListener.h"
#include "NetLibs.h"
#include "NetInstanceBuilder.h"
#include <DoubleQueue.h>
#include <LumpData.h>
#include <Work.h>
#include <Cycle.h>
#include <Socket.h>
#include <Thread.h>
#include <UniqNumGenerater.h>
#include <map>
#include <PoplarPool.h>
#include "NetServiceOrder.h"

/**
* @class NetService
*  - 
*/
class NetworkSession;
class NetService : public CThread{
	typedef std::map<size_t, NetworkSession*> SessionContainer;	
	typedef DoubleQueue<LumpData*> MSG_Q;

	enum{
		DEF_MAX_BUFFER_SIZE=								1024,
		DEF_SHUTDOWN_SERVICE_WAIT_CLOSE_SESISON_TIME=		1000,
		DEF_SHUTDOWN_SERVICE_WAIT_CLOSE_SESISON_COUNT=		5,
		DEF_SESSION_CONTAINER_LOG_TIME=						900,		
	};

public:	
	enum{
		DEF_IDENT_MAX =										3900000000,
	};

	bool startService( WorkListener* event_listener, \
		const char* server_config_name, NetworkConfig* config = 0, \
		size_t buffer_size = DEF_MAX_BUFFER_SIZE );	
	
	NetworkSession* registerSession( const char* ip, int port, \
		WorkListener* event_listener, size_t ident_app = 0 );
	
	int getLastSec(){ return cycle_.lastSec(); }

	NetworkConfig* getNetworkConfig(){ return &network_config_; }

	virtual DEF_THREAD_RETURN run();

	static NetService* Instance();
	static void Shutdown();	

protected:
	
private:	
	NetService();
	virtual ~NetService();	
	
	bool loadEnvironment( const char* server_config_name, NetworkConfig* config );
	void sessionLoop();	
	bool loadEnvironment();		
	
	int process();
	
	Network_IOListener* network_event_listner_;	
	WorkRegistry event_listener_registry_;
	SessionContainer sessions_;	
	Cycle cycle_;
	NetworkConfig network_config_;
	UniqNumGenerater ident_generator_;
	MSG_Q msg_q_;
	NetInstanceBuilder* builder_;
	ObjectPool< LumpData > msg_pool_;

	NetServiceOrder order_;

	CLock session_lock_;
	CLock msg_lock_;

	NetworkStat stat_;

private:
	friend class SessionOverlapped;
	friend class SessionSync;

	size_t getBufferSize();

private:
	friend class KeyParser;
	friend class ByteParser;

	void putMsg( unsigned int ident, char* buffer, size_t size );	

private:
	friend class EPoll_IOListener;
	friend class IOCP_IOListener;
	friend class SELECT_IOListener;

	NetworkSession* registerSession( Socket sock );
};

//#pragma data_seg(".Share_net_service")
static NetService* NetService_ = 0;
//#pragma data_seg()
//#pragma comment(linker, "/SECTION:.Share_net_service,RWS")
